package com.tagit.red5;

/*
 * RED5 Open Source Flash Server - http://www.osflash.org/red5
 * 
 * Copyright (c) 2006-2008 by respective authors (see below). All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or modify it under the 
 * terms of the GNU Lesser General Public License as published by the Free Software 
 * Foundation; either version 2.1 of the License, or (at your option) any later 
 * version. 
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY 
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along 
 * with this library; if not, write to the Free Software Foundation, Inc., 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 */

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.jvoicexml.JVoiceXml;
import org.red5.io.amf3.ByteArray;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
import org.slf4j.Logger;

import com.tagit.speech.SpeechSession;
import com.tagit.speech.SpeechSessionManager;

/**
 * Demo Application for JVoiceXML text implementation.
 * 
 * @author Mohamed Ali
 */
public class Application extends MultiThreadedApplicationAdapter {
	final private Logger log = Red5LoggerFactory.getLogger(this.getClass(),
			"flashMic");

	public IScope appScope;

	/** The JVoiceXML instance */
	public JVoiceXml jvxml;

	private Context context;
	
	public Context envCtx;

	/** Used for synchronised processes */
	public Object lock = new Object();

	private SpeechSessionManager sman = SpeechSessionManager.getInstance();

	@Override
	public boolean appStart(IScope scope) {
		appScope = scope;

		Properties jndiProps = new Properties();

		// Obtain our environment naming context
		Context initCtx;
		try {
			initCtx = new InitialContext();

			envCtx = (Context) initCtx.lookup("java:comp/env");
			
			jndiProps.setProperty(Context.INITIAL_CONTEXT_FACTORY,
					(String) envCtx.lookup("contextFactory"));
			jndiProps.setProperty(Context.PROVIDER_URL,
					(String) envCtx.lookup("providerURL"));
			jndiProps.setProperty("java.naming.rmi.security.manager",
					(String) envCtx.lookup("securityManager"));
			
			log.debug("Loaded JNDI settings " + jndiProps.toString());
		} catch (NamingException e1) {
			log.error("Error Reading Environment Variables", e1);
			return false;
		}

		try {
			context = new InitialContext(jndiProps);			
		} catch (NamingException e) {
			log.error("Error Initializing Context", e);
			return false;
		}
		
		try {
			jvxml = (JVoiceXml) context.lookup("JVoiceXml");
		} catch (NamingException e) {
			log.error("Error Initializing JVoiceXML", e);
			return false;
		}
		return super.appStart(scope);
	}

	/** {@inheritDoc} */
	@Override
	public boolean appConnect(IConnection conn, Object[] params) {

		/* Add the new connection to the connections map */
		String clientId = conn.getClient().getId();
		
		log.info("Creating new session for client " + clientId);

		SpeechSession session = new SpeechSession(clientId, conn, this);

		sman.newSession(session);

		return super.appConnect(conn, params);
	}

	/** {@inheritDoc} */
	@Override
	public void appDisconnect(IConnection conn) {
		String clientId = conn.getClient().getId();
		
		log.info("Client " + clientId + " disconnected");

		SpeechSession session = sman.removeSession(clientId);
		if (session != null) {
			log.info("Closing session");
			session.close();
		}

		super.appDisconnect(conn);
	}
	
	/** Called by the client to set the session language and the microphone sampling rate */
	public void initSettings(String clientID, String lang, int sampleRate) {
		SpeechSession session = sman.getSession(clientID);
		if (session != null) {
			session.initSettings(lang, sampleRate);
		}
	}

	/** Calls a VXML document from the specific URL */
	public void callURL(String clientID, String URL) {
		SpeechSession session = sman.getSession(clientID);
		log.info("Calling " + URL);
		session.callURL(URL);
	}
	
	/** Hangup the call */
	public void hangUp(String clientID) {
		SpeechSession session = sman.getSession(clientID);
		
		session.hangUp();
	}
	
	/** Receives audio frames from the client. Data is assumed to be 16bit PCM compressed array. */
	public int receiveData(String clientID, ByteArray data, int msec) {
		SpeechSession session = sman.getSession(clientID);

		if (session != null) {
			data.uncompress();
			data.position(0);

			double[] samples = new double[data.length() / 2]; // number of 16bit
																// integers in
																// the ByteArray
			int i = 0;
			while (data.bytesAvailable() > 0) {
				// Read signed short values from the ByteArray
				samples[i] = (double) data.readShort();
				i++;
			}
			session.readData(samples, msec);
		}
		return msec;
	}

}
